package etnorservice.etnor_service.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;

import etnorservice.etnor_service.aop.annoution.OperationLog;
import etnorservice.etnor_service.domain.dto.ApiCountDTO;
import etnorservice.etnor_service.domain.dto.ApiLogDTO;
import etnorservice.etnor_service.domain.dto.ApiPublishConfigRequest;
import etnorservice.etnor_service.domain.dto.ParamsDTO;
import etnorservice.etnor_service.domain.po.*;
import etnorservice.etnor_service.domain.response.PolicyBaseResponse;
import etnorservice.etnor_service.domain.vo.*;
import etnorservice.etnor_service.mapper.ApiMapper;
import etnorservice.etnor_service.mapper.ApiPublishConfigMapper;
import etnorservice.etnor_service.mapper.UserMapper;
import etnorservice.etnor_service.request.*;
import etnorservice.etnor_service.service.IApiService;

import etnorservice.etnor_service.utils.SnowflakeIdGenerator;
import etnorservice.etnor_service.utils.UniqueIdGenerator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.SQLException;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.function.Function;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author cc
 * @since 2024-06-30
 */
@Service
public class ApiServiceImpl implements IApiService {
    private static final Logger logger = LoggerFactory.getLogger(ApiServiceImpl.class);

    @Autowired
    ApiMapper apiMapper;
    @Autowired
    UserMapper userMapper;
    @Autowired
    ApiPublishConfigMapper apiPublishConfigMapper;

    @Override
    public List<ApiDTO> getAllApis() {
        return apiMapper.getAllApis();
    }

    @Override
    public List<ApiDTO> getAllApi() {
        return apiMapper.getAllApi();
    }

    @Override
    public List<ApiDTO> getApisByKewordsAndCatelog(String keyword, String catelog) {
        return apiMapper.getApisByKewordsAndCatelog(keyword,catelog);
    }

    @Override
    public List<ApiCategory> apiKinds() {
        return apiMapper.findAllCatelogies();
    }

    @Override
    public List<ApiSelectByTalentIdVO> getApisByTalentId(int talentId) {
        return apiMapper.getApiByTalentId(talentId);
    }

    @Override
    @Transactional
    public int addApi(ApiRequest apiRequest) {
        ApiDTO apiDTO=new ApiDTO();
        apiDTO.setTalentid(apiRequest.getTalentid());
        apiDTO.setApiurl(apiRequest.getApiUrl());
        apiDTO.setName(apiRequest.getName());
        apiDTO.setTesturl(apiRequest.getTestLink());
        apiDTO.setApiapply(apiRequest.getProvider());
        apiDTO.setUpdatetime(LocalDateTime.now());
        apiDTO.setDescription(apiRequest.getDescription());
        apiDTO.setType(Integer.parseInt(apiRequest.getType()));
        apiDTO.setIsneedtoken(Integer.parseInt(apiRequest.getType()));
        apiDTO.setStatus(-2);
        apiDTO.setIcon("REST");
        apiDTO.setApiid(apiRequest.getApiid()+"");
        ApiRejectRequest apiRejectRequest=new ApiRejectRequest();
        apiRejectRequest.setUid(Long.parseLong(apiDTO.getApiid()));
        apiRejectRequest.setCreatetime(new Date());
        apiRejectRequest.setState(1);
        apiRejectRequest.setNote(null);
        apiRejectRequest.setStatus(-1);
        apiRejectRequest.setTime(new Date());
        apiRejectRequest.setApiId(apiDTO.getId());
        apiDTO.setState(1);
        apiMapper.insertApi(apiDTO);
        apiMapper.insertApiRejection(apiRejectRequest);
        return 0;
    }

    @Override
    public List<ApiReviewVO> findApiReviewList() {
        return apiMapper.findReviewApi();
    }

    @Override
    public List<ModeStatusNoteDTO> findModes() {
        return apiMapper.findModes();
    }

    @Override
    public ModeStatusNoteDTO findCurrentMode() {
        return apiMapper.findCurrentMode();
    }

    @Override
    public int changeMode(Integer modeid) {
        return apiMapper.changeMode(modeid);
    }

    @Override
    @Transactional
    public int passApiReview(Long apiId) {
        apiMapper.updateAuditPass(apiId);
        apiMapper.passApiReview(apiId);
        return 0;
    }

    @Override
    @Transactional
    public int rejectAndInsert(ApiRejectRequest apiRejectRequest) {
        Long apiid=Long.parseLong(apiMapper.findApiByid(apiRejectRequest.getApiId()).getApiid());
        apiMapper.rejectApiReview(apiid);
        apiMapper.updateAuditReject(apiid,apiRejectRequest.getNote());

        return 0;
    }

    @Override
    public List<ApiAduit> getAduitList(Integer talentId) {
        return apiMapper.getAduitList(talentId);
    }

    @Override
    public ApiDTO findApiByid(Integer id) {
        return apiMapper.findApiByid(id);
    }

    @Override
    public PolicyBaseResponse findAllPolicy() {
        PolicyBaseResponse policyBaseResponse=new PolicyBaseResponse();
        policyBaseResponse.setApiAlarmPolicies(apiMapper.findAllAlarmPolicy());
        policyBaseResponse.setApiShutdownPolicies(apiMapper.findAllPolicy());
        return policyBaseResponse;
    }

    @Override
    @Transactional
    public int publishApi(PublishRequest request) {

        ApiPublish apiPublish=new ApiPublish();
        apiPublish.setAppid(Long.parseLong(request.getApiId()));
        apiPublish.setState(1);
        apiPublish.setAlarmPolicy(request.getDelayThreshold());
        apiPublish.setShutdownPolicy(request.getOffThreshold());
        apiPublish.setIsgrey(request.getType().equals("gray")?1:0);
        apiPublish.setThreshold(request.getThreshold());
        apiPublish.setPublishTime(new Date());
        apiPublish.setPublishPeople(request.getPublishPeople());
        apiMapper.publishApi(apiPublish);
        apiMapper.changeApiStatus(apiPublish.getAppid(),1);
        apiMapper.changeAuditStatus(apiPublish.getAppid(),2);
        return 0;
    }

    @OperationLog
    @Override
    public ApiDetailsVO findApiById(String apiid) {
        ApiDTO apiById = apiMapper.findApiById(apiid);
        System.out.println("===================>"+apiById);
        if (apiById == null) {
            throw new IllegalArgumentException("接口" + apiid + "不存在");
        }
        try {
            ApiDetailsVO apiDetailsVO = new ApiDetailsVO();


            apiDetailsVO.setApiName(apiById.getName());
            apiDetailsVO.setUpdateTime(apiById.getUpdatetime());
            apiDetailsVO.setPopularity(apiById.getStarts());
            apiDetailsVO.setApiAddress(apiById.getApiurl());
            apiDetailsVO.setResponseFormat(apiById.getResType());
            apiDetailsVO.setRequestMethod(apiById.getRqsType());
            apiDetailsVO.setRequestParams(null);
            apiDetailsVO.setNotes(apiById.getDescription());
            apiDetailsVO.setResponseExample(apiById.getRespose());
            Developer developer = userMapper.findDeveloperByTalentId(apiById.getTalentid() + "");
            apiDetailsVO.setAuthorAvatar(developer==null?"":developer.getIcon());
//            apiDetailsVO.setAuthorId(developer==null?"":developer.getUserId());
//            apiDetailsVO.setAuthorBio(developer==null?"":developer.getNote());
//            apiDetailsVO.setAuthorName(developer==null?"":developer.getName());
            apiDetailsVO.setAuthorName(apiById.getApiapply());
            apiDetailsVO.setAuthorId(apiById.getTalentid()+"");
            apiDetailsVO.setUpdateTime(apiById.getUpdatetime());
            apiDetailsVO.setDescription(apiById.getDescription());
            String note = apiById.getNote();
            note = note.replace("\r\n", "").replace("\n", "");
            apiDetailsVO.setNotes(note);
            apiDetailsVO.setRequestParamList(apiMapper.findApiParams(apiById.getApiid() + ""));
            apiDetailsVO.setBugFixHistory(apiMapper.findApiBug(apiById.getApiid() + ""));
            apiDetailsVO.setResponseParams(apiMapper.findApiParamsOut(apiById.getApiid() + ""));
            apiDetailsVO.setNeedToken(apiById.getIsneedtoken());
            return apiDetailsVO;
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }

    }

    @Override
    public String findTestUrl(String apiid) {
        return apiMapper.findApiTestUrl(apiid);
    }

    @Override
    public void saveApiLog(ApiLog apiLog) {
      apiMapper.apiLogSave(apiLog);
    }

    @Override
    public List<ApiLog> findLogs(String apiid) {
        return apiMapper.findLogs(apiid);
    }

    @Override
    public void submitApi(ApiSubmission apiSubmission) {
        //判断接口作者信息，如果是系统内用户则表示为原创
        Integer account = apiSubmission.getTalentId();
        User roleByAccount = userMapper.findRoleByAccount(account);
        if(roleByAccount!=null){
            apiSubmission.setApiAuthor(roleByAccount.getUsername());
        }
        ApiDTO apiDTO=new ApiDTO();
        apiDTO.setApiapply(apiSubmission.getApiAuthor());
        apiDTO.setStatus(-2);
        apiDTO.setIsneedtoken(0);
        apiDTO.setName(apiSubmission.getApiTitle());
        // 定义 workerId 和 dataCenterId
        long workerId = 1L;
        long dataCenterId = 1L;
        // 创建 SnowflakeIdGenerator 实例
        SnowflakeIdGenerator idGenerator = new SnowflakeIdGenerator(workerId, dataCenterId);
        // 调用 nextId 方法生成全局唯一的 ID
        long uniqueId = idGenerator.nextId();
        apiDTO.setApiid(uniqueId+"");
        apiDTO.setNote("无");
        apiDTO.setStarts(200);
//        apiDTO.setCall(apiSubmission.getRequestExample());
        apiDTO.setRespose(apiSubmission.getResponseExample());
//        apiDTO.setUpdatetime();
        apiDTO.setTesturl(apiSubmission.getRequestExample());
        apiDTO.setApiurl(apiSubmission.getApiUrl());
        apiDTO.setIcon("REST");
        apiDTO.setDescription(apiSubmission.getApiDescription());
        apiDTO.setType(1);
        apiDTO.setTalentid(apiSubmission.getTalentId());
        apiDTO.setIsCreate(1);
        apiDTO.setResType(apiSubmission.getResponseFormat());
        apiDTO.setRqsType(apiSubmission.getRequestMethod());
        apiDTO.setIsneedtoken(apiSubmission.getNeedToken());
        apiDTO.setImageLinks(apiSubmission.getImageLink());
        try {
            apiMapper.insertApi(apiDTO);
        }catch (Exception e){
            logger.error("插入api失败"+e.getMessage());
        }



    }

    @Override
    public List<ApiManagementVO> findApiList(ApiSearchRequest request) {
        int offset = (request.getCurrentPage() - 1) * request.getPageSize();
        request.setOffset(offset); // 设置偏移量

        return apiMapper.findApiList(request);
    }

    @Override
    public ApiCountDTO getApiCounts() {
        return apiMapper.getApiCounts();
    }

    @Override
    public List<ApiDTO> getApisByAccount(String talentid) {
        List<ApiDTO> apisByAccount = apiMapper.getApisByAccount(talentid);
        for(ApiDTO apiDTO : apisByAccount){
            ApiPublishConfig byApiId = apiPublishConfigMapper.getByApiId(Long.parseLong(apiDTO.getApiid()));
            if(byApiId!=null){
                apiDTO.setApiLimit(byApiId.getRequestThreshold());
                apiDTO.setMode(byApiId.getPublishType());
            }
            int i = apiMapper.countApiCalls(apiDTO.getApiid());
            apiDTO.setApiRequestCount(i);

        }
        return apisByAccount;
    }

    @Override
    public List<ParamsDTO> getParams(String apiid) {
        return apiMapper.getParams(apiid);
    }

    @Override
    @Transactional
    public void publishApi(ApiParamsRequest apiParamsRequest) throws SQLException {
        logger.info("Starting publishApi with deployType: {}", apiParamsRequest.getDeployType());

        // 灰度发布
        if (apiParamsRequest.getDeployType().equals("gray")) {
            logger.info("Handling gray deployment");
            // 灰度发布的逻辑
        }
        // 全量发布
        if (apiParamsRequest.getDeployType().equals("full")) {
            logger.info("Handling full deployment");
            // 发布 API
            apiMapper.publishApiByApiId(apiParamsRequest.getApiId());
            // 将发布记录存到表 api_publish
            apiMapper.fullPublish(apiParamsRequest.getApiId(), new Date(), apiParamsRequest.getTalentId());
            // 保存参数
            List<ApiParamsRequest.Parameters> parameters = apiParamsRequest.getParameters();
            for (ApiParamsRequest.Parameters parameters1 : apiParamsRequest.getParameters()) {
                apiMapper.insertParams(
                        apiParamsRequest.getApiId(),
                        parameters1.getName(),
                        parameters1.getType(),
                        parameters1.getRequired() == true ? 1 : 0,
                        parameters1.getDescription()
                );
            }
        }

        logger.info("Finished publishApi");
    }

    @Override
    public void insertApiNew(ApiSubmission apiSubmission) {
     //判断接口作者信息，如果是系统内用户则表示为原创
        String account = apiSubmission.getApiAuthor();
        User roleByAccount = userMapper.findRoleByAccount(Integer.parseInt(account));
        logger.info("用户"+roleByAccount);
    }

    @Override
    public List<ApiCategory> findAllCatelogies() {
        return apiMapper.findAllCatelogies();
    }

    @Override
    public void approveApi(String apiid) {
          apiMapper.apiStatusChange(apiid,10);
    }

    @Transactional
    @Override
    public void rejectApi(ApiReject apiReject) throws SQLException {
        apiMapper.apiStatusChange(apiReject.getApiid(),-3);
        apiMapper.rejectApi(apiReject);
    }

    @Override
    public ApiReject findReject(String apiid) {
        return apiMapper.findReject(apiid);
    }

    @OperationLog
    @Override
    public void insertApiRequestLog(ApiRequestLog apiRequestLog) throws SQLException {
        int result=apiMapper.insertApiRequestLog(apiRequestLog);
        if(result==0){
            throw new SQLException(apiRequestLog.getApiid()+"接口日志插入失败");
        }
    }

    @Override
    public ApiLogDTO findApiRequestLog(String apiid) {
        List<ApiRequestStat> apiRequestStatList= apiMapper.findApiRequestLog(apiid);
        int avgCount=0;
        for(ApiRequestStat apiRequestStat:apiRequestStatList){
            avgCount+=apiRequestStat.getResponseTime();
        }
        ApiLogDTO apiLogDTO=new ApiLogDTO();
        apiLogDTO.setApiRequestStatList(apiRequestStatList);
        if(apiRequestStatList.size()>0){
            apiLogDTO.setAvgCount(avgCount/apiRequestStatList.size());
        }

        return apiLogDTO;
    }

    @Override
    public Integer getApiCount(String apiid) {
        return apiMapper.getApiCount(apiid);
    }

    @Override
    public List<ApiStatisticsDTO> getApiStatistics() {
        return apiMapper.getApiStatistics();
    }

    @Override
    public void addApiParams(List<ApiParams> apiParams) {
        try {

            apiMapper.batchInsert(apiParams);
            apiMapper.apiStatusChange(apiParams.get(0).getApiId()+"",20);

        }catch (Exception e){
            e.printStackTrace();
        }

    }

    @Override
    public boolean validateApiOwnership(Long apiId, String account) {
        // 查询API是否属于该用户
        return apiMapper.checkApiOwnership(apiId, account) > 0;
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void savePublishConfig(ApiPublishConfigRequest request) throws Exception {
        // 检查API是否存在
        if (apiMapper.checkApiExists(request.getApiId()) == 0) {
            throw new Exception("API不存在");
        }
        // 构建发布配置对象
        ApiPublishConfig config = new ApiPublishConfig();
        config.setApiId(request.getApiId());
        config.setPublishType(request.getPublishType());
        config.setRequestThreshold(request.getRequestThreshold());
        config.setCreateTime(new Date());
        config.setUpdateTime(new Date());
        config.setVersion(request.getVersion());
        config.setStatus(1);
        // 检查是否已存在配置
        ApiPublishConfig existingConfig = apiPublishConfigMapper.getByApiId(request.getApiId());
        if (existingConfig != null) {
            // 更新现有配置
            config.setId(existingConfig.getId());
            apiPublishConfigMapper.updateConfig(config);
        } else {
            System.out.println("=======================>"+config);
            // 创建新配置
            apiPublishConfigMapper.insertConfig(config);
        }
        // 更新API状态为预发布状态(20)
        apiMapper.changeAuditStatus(request.getApiId(), 3);
    }
    @Override
    public ApiPublishConfig getPublishConfig(Long apiId) {
        return apiPublishConfigMapper.getByApiId(apiId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void offlineApi(Long apiId) throws Exception {
        // 检查API是否存在
        if (apiMapper.checkApiExists(apiId) == 0) {
            throw new Exception("API不存在");
        }

        // 更新API状态为下架状态(0)
        System.out.println("下架id==============>"+apiId);
        apiMapper.changeApiStatus(apiId, -1);



        // 禁用发布配置
        apiPublishConfigMapper.disableConfig(apiId);
    }

    @Override
    public void reAudit(Long apiId) {
        apiMapper.changeApiStatus(apiId,-2);
    }

    @Override
    public ApiPublishConfig getApiConfig(Long apiId) {
        ApiPublishConfig byApiId = apiPublishConfigMapper.getByApiId(apiId);
        return byApiId;
    }

    @Override
    public Integer countApiCalls(Long apiId) {
        return apiMapper.countApiCalls(apiId+"");
    }

    @Override
    public void publishApi(String apiid) {

        ApiPublishConfig byApiId = apiPublishConfigMapper.getByApiId(Long.parseLong(apiid));
        if(byApiId==null){
            //如果老版本没配置，默认插入全量配置
            ApiPublishConfig config = new ApiPublishConfig();
            config.setApiId(Long.parseLong(apiid));
            config.setPublishType("full");
            config.setRequestThreshold(0);
            config.setCreateTime(new Date());
            config.setUpdateTime(new Date());
            config.setVersion("v1.0.0");
            config.setStatus(1);
            apiPublishConfigMapper.insertConfig(config);
            apiMapper.changeApiStatus(Long.parseLong(apiid), 1);
        }else {
            apiPublishConfigMapper.openConfig(byApiId.getId());
            apiMapper.changeApiStatus(Long.parseLong(apiid), 1);
        }
    }

    @Override
    public ApiToken findApiToken(Long apiid,Long userId) {
        return apiMapper.findApiToken(apiid,userId);
    }


}
